#pragma once
#ifndef POLY_HPP
# define POLY_HPP

#include "vector.hpp"

namespace etl
{

namespace detail
{

template <typename T, ::std::size_t N, ::std::size_t I>
inline constexpr
typename ::std::enable_if<I == N - 2, T>::type
horner_step(::etl::vector<T, N> const& v, T const tmp, T const x)
{
  return tmp * x + v(I + 1);
}

template <typename T, ::std::size_t N, ::std::size_t I>
inline constexpr
typename ::std::enable_if<I != N - 2, T>::type
horner_step(::etl::vector<T, N> const& v, T const tmp, T const x)
{
  return horner_step<T, N, I + 1>(v, tmp * x + v(I + 1), x);
}

}

template <typename T, ::std::size_t N>
typename ::std::enable_if<N == 1, T>::type
inline constexpr polyval(::etl::vector<T, N> const& v, T const)
{
  return v(0);
}

template <typename T, ::std::size_t N>
typename ::std::enable_if<(N > 2), T>::type
inline constexpr polyval(::etl::vector<T, N> const& v, T const x)
{
  return detail::horner_step<T, N, 0>(v, v(0), x);
}

}

#endif // POLY_HPP
